#include "Model.h"
#include <sstream>
#include <fstream>
#include <iostream>
#include <stdlib.h>

#ifdef __APPLE__
	#include <OpenGL/OpenGL.h>
	#include <GLUT/glut.h>
#else
	#include <GL/glut.h>
#endif

Model::Model(void)
{
	pos.SetPoints(0, 0, 0);
}

void Model::LoadFile(string path)
{
	ifstream inFile (path.c_str());
    string line;

	std::cout << "loading " << path << endl;
    while (getline (inFile, line))
    {

		switch(line[0])
		{
			case 'v':
				if (line[1] == 'n')
				{
					ParsePoint(line, "normal");
				}
				else if (line[1] == 't')
				{
					// ignore texture for now
					//ParsePoint(line, "texture");
				}
				else 
				{
					ParsePoint(line, "vertex");
				}
				break;
			
			case 'f':
				ParseTriangle(line);
				break;

			default:
				break;
		}
    }
}

void Model::ParsePoint(string line, string type)
{
	istringstream linestream(line);
    string item;
	Point p;
	int count = 0;

	while (getline (linestream, item, ' '))
	{
		if (count == 1)
		{
			p.x = atof(item.c_str());
		}
		else if (count == 2)
		{
			p.y = atof(item.c_str());
		}
		else if (count == 3)
		{
			p.z = atof(item.c_str());
		}
		count++;
	}

	if (type == "vertex")
	{
		vertices.push_back(p);
	}
	else if (type == "normal")
	{
		normals.push_back(p);
	}
}

void Model::ParseTriangle(string line)
{
	istringstream linestream(line);
    string item;
	int count = 0;
	vector<int> list;

	while (getline (linestream, item, ' '))
	{
		if (count > 0)
		{
			int slashIndex = 0;
			for (unsigned int i = 0; i < item.size(); i++)
			{
				if (item[i] != '/')
				{
					slashIndex++;
				}
				else
				{
					break;
				}
			}
			string vertexIndex = item.substr(0, slashIndex);
			list.push_back(atoi(vertexIndex.c_str()));
		}
		count++;
	}

	// indexes start at 0, so subtract 1
	int a = list[0] - 1;
	int b = list[1] - 1;
	int c = list[2] - 1;

	Triangle triangle(vertices[a], vertices[b], vertices[c]);
	triangle.SetNormal(normals[c]);

	triangles.push_back(triangle);
}

void Model::DrawWireFrame()
{
	glDisable(GL_LIGHTING);
    glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

	glBegin(GL_TRIANGLES);

	for (unsigned int i = 0; i < triangles.size(); i++)
	{
		glVertex3f(triangles[i].a.x, triangles[i].a.y, triangles[i].a.z);
		glVertex3f(triangles[i].b.x, triangles[i].b.y, triangles[i].b.z);
		glVertex3f(triangles[i].c.x, triangles[i].c.y, triangles[i].c.z);
	}

	glEnd();

}

void Model::DrawModel()
{
	glEnable(GL_LIGHTING);
	glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
	glBegin(GL_TRIANGLES);

	for (unsigned int i = 0; i < triangles.size(); i++)
	{
		glNormal3f(triangles[i].normal.x, triangles[i].normal.y, triangles[i].normal.z); 
		glVertex3f(triangles[i].a.x, triangles[i].a.y, triangles[i].a.z);
		glVertex3f(triangles[i].b.x, triangles[i].b.y, triangles[i].b.z);
		glVertex3f(triangles[i].c.x, triangles[i].c.y, triangles[i].c.z);
	}

	glEnd();
}